package com.bjy.qa.agent.response;

import org.apache.commons.lang.StringUtils;
import org.apache.http.Header;
import org.hamcrest.core.Is;
import org.hamcrest.core.StringContains;
import org.junit.Assert;

import java.io.InputStream;
import java.util.Map;

/**
 * 自定义的 HttpResponse
 */
public class HttpResponse extends Response {
    private Integer status; // 响应状态码
    private String callback; // 回调函数名
    private Header[] headers; // 响应头

    /**
     * 构造函数
     * @param status 响应状态码
     * @param body 响应体
     * @param headers 响应头
     */
    public HttpResponse(Integer status, String body, Header[] headers) {
        super(body, null);
        this.status = status;
        this.headers = headers;
    }

    /**
     * 构造函数
     * @param status 响应状态码
     * @param body 响应体
     */
    public HttpResponse(Integer status, String body) {
        super(body, null);
        this.status = status;
    }

    /**
     * 构造函数
     * @param status 响应状态码
     * @param body 响应体（InputStream）
     * @param headers 响应头
     */
    public HttpResponse(Integer status, InputStream body, Header[] headers) {
        super(body, null);
        this.status = status;
        this.headers = headers;
    }

    /**
     * 校验响应
     * @param expected 预期结果
     */
    public void verify(Map<String, String> expected) {
        String expectedStatus = (String) expected.get("status");
        assertStatus(expectedStatus);
        assertCallbackFunctionName((String) expected.get("callback"));
        assertHeaders(expected);
        super.verify(expected);
    }

    /**
     * 校验响应头
     * @param expectedHeaders 预期响应头
     */
    private void assertHeaders(Map<String, String> expectedHeaders) {
        for (Map.Entry entry : expectedHeaders.entrySet()) {
            String header = (String) entry.getKey();
            if (header.startsWith("header-")) {
                String headerName = header.substring("header-".length());
                String expected = (String) entry.getValue();
                String actual = getHeaderContent(headerName);

                if (StringUtils.isNotBlank(actual))
                    Assert.assertThat("http header " + headerName, actual, StringContains.containsString(expected));
                else if (!expected.equalsIgnoreCase(actual))
                    Assert.fail("期望存在http header " + headerName);
            }
        }
    }

    /**
     * 校验回调函数名
     * @param expectCallback 预期回调函数名
     */
    private void assertCallbackFunctionName(String expectCallback) {
        if (StringUtils.isNotBlank(expectCallback))
            Assert.assertThat("js callback function name is not equals.", this.callback, Is.is(expectCallback));
    }

    /**
     * 校验响应状态码
     * @param expectedStatus 预期响应状态码
     */
    private void assertStatus(String expectedStatus) {
        if (StringUtils.isNotBlank(expectedStatus))
            Assert.assertThat("http request status is not equals.", this.status.toString(), Is.is(expectedStatus));
    }

    /**
     * 获取响应头内容
     * @param headerName 响应头名称
     * @return 响应头内容
     */
    private String getHeaderContent(String headerName) {
        if (this.headers == null) return "";
        for (int i = 0; i < this.headers.length; i++) {
            if (headerName.equalsIgnoreCase(this.headers[i].getName())) {
                return this.headers[i].getValue();
            }
        }
        return "";
    }

    /**
     * 设置回调函数名
     * @param callback 回调函数名
     */
    public void setCallback(String callback) {
        this.callback = callback;
    }

    /**
     * 获取回调函数名
     * @return
     */
    public String getCallback() {
        return this.callback;
    }

    /**
     * 获取响应状态码
     * @return
     */
    public Integer getStatus() {
        return this.status;
    }

    /**
     * 设置响应状态码
     * @param status
     */
    public void setStatus(Integer status) {
        this.status = status;
    }

    public String toString() {
        return "HttpResponse{status=" + this.status + ", body='" + this.body + '\'' + '}';
    }
}
